﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Threading;

namespace Invini.Training
{
    public delegate void TrainingTriggerEventHandler(TrainingTriggerBase trainingTrigger);

    [ContentProperty("Actions")]
    public abstract class TrainingTriggerBase
    {
        public class TrainingActionsCollection : List<TrainingActionBase> { }

        public event TrainingTriggerEventHandler ConditionSatisfied;
        public event TrainingTriggerEventHandler Started;
        public event TrainingTriggerEventHandler Completed;

        public string Name
        {
            get;
            set;
        }

        private bool _isConditionSatisfied;
        public bool IsConditionSatisfied
        {
            get { return this._isConditionSatisfied; }
            set
            {
                if (this._isConditionSatisfied == value)
                    return;

                lock (this.conditionLock)
                {
                    this._isConditionSatisfied = value;

                    if (this._isConditionSatisfied && this.ConditionSatisfied != null)
                        this.ConditionSatisfied(this);
                }
            }
        }
        private object conditionLock = new object();

        private bool _isCompleted;
        public bool IsCompleted
        {
            get { return this._isCompleted; }
            set
            {
                if (this._isCompleted == value)
                    return;

                this._isCompleted = value;

                if (this._isCompleted && this.Completed != null)
                    this.Completed(this);
            }
        }

        public TrainingActionsCollection Actions
        {
            get;
            set;
        }

        private uint numOfActionsExecuted = 0;

        public TrainingTriggerBase()
        {
            this.Actions = new TrainingActionsCollection();
        }
        public virtual void Prepare() { }
        public void EnsureConditionSatisfaction(TrainingTriggerEventHandler eventHandler)
        {
            lock(this.conditionLock)
            {
                if (this.IsConditionSatisfied)
                {
                    eventHandler(this);
                    return;
                }

                this.ConditionSatisfied += eventHandler;
            }
        }
        
        public virtual void Execute()
        {
            if (this.Started != null)
                this.Started(this);

            if (this.Actions == null || this.Actions.Count == 0)
            {
                this.IsCompleted = true;
                return;
            }

            foreach (TrainingActionBase action in this.Actions)
            {
                action.Completed += this.action_Completed;
                action.Execute();
            }
        }

        public virtual void Clear()
        {
            foreach (TrainingActionBase action in this.Actions)
                action.Clear();
        }
        public virtual void Dispose()
        {
            this.Clear();

            foreach (TrainingActionBase action in this.Actions)
                action.Dispose();
        }

        private void action_Completed(TrainingActionBase action)
        {
            this.numOfActionsExecuted++;
            if (this.numOfActionsExecuted >= this.Actions.Count)
                this.IsCompleted = true;
        }
    }
}
